#!/usr/bin/python
# -*- coding: utf-8 -*-

'''
目的：将此文件作为主文件，可同时实现simhash|TF_IDF|jaccard三种方法的相似度计算，代码简洁，便于迁移
输入：情报文件，demo.txt,10000条
输出：1、两两情报的相似度，method.txt文件
    2、情报相似度高于某阈值的相似情报输出 method.csv文件
    3、各去重方法之间的对比，compare.csv文件
'''

#导入模块
import thulac
from sklearn.feature_extraction.text import TfidfVectorizer
import numpy as np
import csv
from scipy.linalg import norm
#simhash手动编写模块
from simhash_jieba_weight import cut_words_jieba,compute_simhash_similarity
'''
记录日志参数
'''
import sys
sys.path.append("..")
from log_tool import logTool  #调入日志文件
LOG_PATH = "./log_note"#设置日志输出存储路径
log = logTool(LOG_PATH)#传入存储路径

# 对比结果的输出路径
# csv_writer_2= csv.writer(open('./result/compare.csv', 'w', encoding='utf-8-sig', newline=''))

#获取中文停用词
stopwordsPath = '../ChineseStopwords.txt'
f = open(stopwordsPath,'r')
stopwords = [word for word in f.read().split('\n')]
thu = thulac.thulac(seg_only=True) #seg_only只分词，不考虑词性,,导入分词工具

#分别
def cut_words(line):
    '''
    :param line: 原始文本
    :return: 去除停用词和分词后的文本,类型为str
    '''
    line = thu.cut(line,text=True)#text=true,获取str类型的文本
    #这里加一个正则匹配去除符号
    # line = re.sub(r'[^\w\s]','',line)#去除标点符号
    cut_line =' '.join([word  for word in line.split(' ') if word not in stopwords])
    return cut_line

#词向量，计算余弦相似度
def compute_tfidf_similarity(s1, s2):
    '''
    :param s1: 文本1 str
    :param s2: 文本2 str
    :return: 余弦相似度 float
    '''
    # 转化为TF矩阵
    corpus = [s1, s2]#语料['str str','str str']格式,以空格区分
    vectors = TfidfVectorizer().fit_transform(corpus).toarray()
    # 计算余弦距离，范围为[-1,1]，通过公式(0.5cos+0.5)归一化至[0,1]区间
    cos_sim = 0.5*(np.dot(vectors[0], vectors[1]) / (norm(vectors[0]) * norm(vectors[1])))+0.5
    return cos_sim

#基于概率统计，杰德卡相似系数
def compute_jaccard_similarity(s1: str, s2: str) -> float:
    word_set1 = set(s1.strip(" ").split(" "))
    word_set2 = set(s2.strip(" ").split(" "))
    jaccard_sim = len(word_set1 & word_set2) / len(word_set1 | word_set2)
    return jaccard_sim

def get_data(file_path,similar_path,repeat_path,method,thre,k=0):
    '''
    :param file_path: 情报位置
    :param similar_path: 两两比较相似度存储位置
    :param repeat_path: 重复情报存储位置
    :param compare_path: 方法对比结果
    :param method: 使用的去重方法
    :param thre: 认定重复的阈值
    :param k: 重复的个数初始计数为0
    :return:nothing
    '''
    f2 = open(similar_path + method + '.txt', 'w')
    csv_writer = csv.writer(open(repeat_path + method + '.csv', 'w', encoding='utf-8-sig', newline=''))

    with open(file_path,'r',encoding='utf-8') as f1:
        inllg_list = f1.readlines()
        #不同的切词方式
        log.info('start cut words')
        if method == 'simhash':
            cut_inllg = cut_words_jieba(inllg_list)
        else:
            cut_inllg = [cut_words(data.strip()) for data in inllg_list]  # 分词
        log.info('end cut words')
        log.info('start '+method+' compute ')
        #不同的计算方法
        for i in range (0,len(cut_inllg)):
            for j in range (i+1,len(cut_inllg)):
                similar = eval('compute_'+method+'_similarity')(cut_inllg[i],cut_inllg[j])#eval把字符串转换为可以调用的图像
                f2.write(method+','+str(i)+','+str(j)+','+str(similar)+'\n')#按照文章序号的格式保存
                if similar > thre:
                    k+=1
                    csv_writer.writerow([str(k),inllg_list[i],inllg_list[j],str(similar)])
                    # csv_writer_2.writerow([str(k),str(method),str(thre),str(i+1),str(j+1),str(similar)])#
            print('the ' + str(i) + 'intelligence compare finish')
        log.info('end '+method+' compute ')
        f2.close()

if __name__=='__main__':
    for method in [('tfidf', 0.74), ('jaccard', 0.3), ('simhash', 0.77)]:
        get_data(file_path='../data/demo_10000.txt', similar_path='./result/', repeat_path='./result/', method=method[0],
                 thre=method[1])

#优化方向
#1、分词应放到方法的外面，三个统一，这样会节省分词时间，先统一使用jieba分词
#2、两两比较的算法需要优化，查找当前比较成熟的算法。



